function Ajax(url, callback, userdata) {
	this.http_request = false;
	this.callback = callback;
	this.userdata = userdata;
	this.url = url;
	this.method = 0; /* 0: GET, 1: POST */
	this.params = null;
	this.data = null;
	this.timer = null;
	this.retry = 0;
	this.retry_count = 1;

	this.free = function () {
		this.retry_count = 1;
		clearTimeout(this.timer);
	};

	this.params_generate = function () {
		var i;
		var str_arr = new Array();
		var str;

		if (this.params == null)
			return;

		for (i = 0; i < this.params.length; ++i) {
			if (this.params[i][1].length > 0) {
				/* Encode value */
				this.params[i][1] = encodeURIComponent(this.params[i][1]);
				str_arr.push(this.params[i].join("="));
			}
		}

		str = str_arr.join("&");
		str_arr = null;

		return str;
	};

	this.make_request = function () {
		var param;

		/* Stop any request in process */
		clearTimeout(this.timer);

		if (window.XMLHttpRequest) { // Mozilla, Safari,...
			this.http_request = new XMLHttpRequest();
		} else if (window.ActiveXObject) { // IE
			try {
				this.http_request = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				try {
					this.http_request = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e) {}
			}
		}

		if (!this.http_request) {
			alert('Giving up :( Cannot create an XMLHTTP instance');
			return false;
		}

		this.http_request.onreadystatechange = function(_self) { 
			return function (e) {
				_self.handler();
			}
		} (this);

		if (this.method == 0) {
			this.http_request.open('GET', this.url, true);
			this.http_request.send(null);
		} else {
			param = this.params_generate();
			this.http_request.open('POST', this.url, true);
			this.http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			this.http_request.setRequestHeader("Content-length", param.length);
			this.http_request.setRequestHeader("connection", "close");
			this.http_request.send(param);
		}
	};

	this.handler = function () {
		if (this.http_request.readyState == 4) {
			if (this.http_request.status == 200) {
				this.data = eval('(' + this.http_request.responseText + ')');
				this.callback(this.data, this.userdata);
			} else {
				if (this.retry > 0) {
					if (this.retry_count >= this.retry)
						return;

					this.retry_count++;
				}

				/* Retry after 3 seconds */
				this.timer = setTimeout(function (_self) {
					return function (e) {
						_self.make_request();
					};
				} (this), 3000);
			}
		}
	};
}

